/*******************************************************************************
 * Copyright 2011-2012 Dik Grapendaal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package sh.grapendaal.tsuushin.service;

import java.util.List;

import sh.grapendaal.tsuushin.message.User;

public interface PermissionService extends Service {
	/**
	 * The permission name which indicates that a certain user is a bot owner.
	 */
	String PERMISSION_BOT_OWNER = "owner";

	/**
	 * Registers a new permission. If the method returns true, the permission
	 * was successfully registered and can be used.
	 * 
	 * @param permission
	 *            The permission to register.
	 * @return Whether the permission was successfully registered.
	 */
	boolean registerPermission(String permission);

	/**
	 * Unregisters a registered permission. If the method returns true, the
	 * permission was successfully unregistered. The permission will be removed
	 * from all users who possess the permission. This action is not reversible.
	 * 
	 * @param permission
	 *            The permission to unregister.
	 * @return Whether the permission was successfully unregistered.
	 */
	boolean unregisterPermission(String permission);

	/**
	 * Checks whether the given permission is registered with the Permission
	 * Service.
	 * 
	 * @param permission
	 *            The permission to check.
	 * @return True when the permission is registered and can be used.
	 */
	boolean permissionExists(String permission);

	/**
	 * Returns a list of permissions which can be granted to or revoked from
	 * users.
	 * 
	 * @return A list of usable permissions.
	 */
	List<String> getUsablePermissions();

	/**
	 * Adds a user without a password and without any permission, which can then
	 * be granted permissions.
	 * 
	 * @param user
	 *            The user to add.
	 */
	void addUser(User user);

	/**
	 * Adds a user who needs to login with the given hashed password, without
	 * any permission.
	 * 
	 * @param user
	 *            The user to add.
	 * @param hashedPassword
	 *            The hashed password for this user.
	 * @param initialIdentified
	 *            True to set this user as identified immediately. If false, the
	 *            user will need to identify before being the permissions are
	 *            granted.
	 */
	void addUser(User user, String hashedPassword, boolean initialIdentified);

	/**
	 * Removes a user along with their permissions.
	 * 
	 * @param user
	 *            The user to remove.
	 */
	void removeUser(User user);

	/**
	 * Indicates whether we know the given user.
	 * 
	 * @param user
	 *            The user to lookup.
	 * @return True when we know him.
	 */
	boolean isUserKnown(User user);

	/**
	 * Grants the given user the given permission. Users have to be added to the
	 * Permission Service before granting them permissions using one of the
	 * {@link addUser()} methods.
	 * 
	 * @param user
	 *            The user to grant the permission.
	 * @param permission
	 *            The permission to grant.
	 * @return False if the user was already granted the permission.
	 * @throws IllegalArgumentException
	 *             If the given user is not known by the Permission Service.
	 */
	boolean grantPermission(User user, String permission);

	/**
	 * Revokes the given permission from the given user. Users have to be known
	 * by the Permission Service before revoking permission from them. If a user
	 * has been removed using the {@link removeUser()} method, then all
	 * permissions the user had will be gone forever. They will not be restored
	 * if the user gets readded.
	 * 
	 * @param user
	 *            The user to revoke the permission from.
	 * @param permission
	 *            The permission to revoke.
	 * @return False if the user did not have the permission.
	 * @throws IllegalArgumentException
	 *             If the given user is not known or the permission is not
	 *             registered.
	 */
	boolean revokePermission(User user, String permission);

	/**
	 * Tells whether the given user was granted the given permission. This can
	 * then be used to unlock otherwise locked functionality, for instance bot
	 * managing tasks.
	 * 
	 * @param user
	 *            The user to check.
	 * @param permission
	 *            The permission to look for.
	 * @return True if the user possesses the given permission.
	 * @throws IllegalArgumentException
	 *             If the given user is not known or the permission is not
	 *             registered.
	 */
	boolean hasPermission(User user, String permission);

	/**
	 * Shortcut for the {@link hasPermission()} method which checks if the given
	 * user has the built-in "owner" permission.
	 * 
	 * @param user
	 *            The user to check.
	 * @return True if the user is an owner.
	 * @throws IllegalArgumentException
	 *             If the given user is not known or the permission is not
	 *             registered.
	 */
	boolean isBotOwner(User user);
}
